package jbase.project.system.util;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import jbase.project.system.exception.SysException;

/**
 * @author UNIVERSE
 */
public class CommonMethod {

	private static CommonMethod instance;

	public static final CommonMethod getInstance() {
		if (instance == null) {
			instance = new CommonMethod();
		}
		return instance;
	}

	public void copySimplePropsToMap(Map<String, Object> map, Object bean, String... propNames) {
		Class<?> clazz = bean.getClass();
		if (propNames != null && bean != null)
			for (String propName : propNames) {
				try {
					Method method = clazz.getMethod(
							"get" + propName.substring(0, 1).toUpperCase() + propName.substring(1), new Class<?>[] {});
					map.put(propName, method.invoke(bean));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
	}

	public String makeContainsRegxIgnoreCase(String ori) {
		char[] chs = ori.toCharArray();
		String reg = "";
		for (int i = 0; i < chs.length; i++) {
			char ch = chs[i];
			String c = new String(new char[] { ch });
			if (c.equals(".")) {
				reg += "[\\" + c + "]";
			} else if (c.equals("\\")) {
				reg += "[\\" + c + "]";
			} else if (c.equals("[")) {
				reg += "[\\" + c + "]";
			} else if (c.equals("]")) {
				reg += "[\\" + c + "]";
			} else if (c.equals("{")) {
				reg += "[\\" + c + "]";
			} else if (c.equals("}")) {
				reg += "[\\" + c + "]";
			} else if (c.equals(" ")) {
				reg += "[\\s]";
			} else if (c.equals("^")) {
				reg += "[\\^]";
			} else if (c.equals("*")) {
				reg += "[\\" + c + "]";
			} else if (!c.toUpperCase().equals(c.toLowerCase())) {
				reg += "[" + c.toUpperCase() + c.toLowerCase() + "]";
			} else {
				reg += "[" + c + "]";
			}
		}
		return ".*" + reg + ".*";
	}

	public <T extends Object> T baseCast(Object source, Class<T> targetClazz) throws SysException {
		if (source == null) {
			return (T) source;
		} else {
			Class<?> sourceClazz = source.getClass();
			if (sourceClazz == targetClazz || targetClazz.isAssignableFrom(sourceClazz)) {
				return (T) source;
			} else {
				String sourceClazzName = sourceClazz.getName();
				String targetClazzName = targetClazz.getName();
				switch (sourceClazzName) {
				case "java.lang.String":
					String value = (String) source;
					switch (targetClazzName) {
					case "java.lang.Integer":
						if (value.matches("-?\\d+")) {
							return (T) (Object) Integer.parseInt(value);
						} else {
							throw new SysException("--不能转换!--");
						}
					case "int":
						if (value.matches("-?\\d+")) {
							return (T) (Object) Integer.parseInt(value);
						} else {
							throw new SysException("--不能转换!--");
						}
					case "java.lang.Long":
						if (value.matches("-?\\d+")) {
							return (T) (Object) Long.parseLong(value);
						} else {
							throw new SysException("--不能转换!--");
						}
					case "long":
						if (value.matches("-?\\d+")) {
							return (T) (Object) Long.parseLong(value);
						} else {
							throw new SysException("--不能转换!--");
						}
					case "java.lang.Float":
						if (value.matches("(\\d+\\.\\d+|\\d+|\\.\\d+)")) {
							return (T) (Object) Float.parseFloat(value);
						} else {
							throw new SysException("--不能转换!--");
						}
					case "float":
						if (value.matches("(\\d+\\.\\d+|\\d+|\\.\\d+)")) {
							return (T) (Object) Float.parseFloat(value);
						} else {
							throw new SysException("--不能转换!--");
						}
					case "java.lang.Double":
						if (value.matches("(\\d+\\.\\d+|\\d+|\\.\\d+)")) {
							return (T) (Object) Double.parseDouble(value);
						} else {
							throw new SysException("--不能转换!--");
						}
					case "double":
						if (value.matches("(\\d+\\.\\d+|\\d+|\\.\\d+)")) {
							return (T) (Object) Double.parseDouble(value);
						} else {
							throw new SysException("--不能转换!--");
						}
					case "java.lang.Boolean":
						if (value.toUpperCase().equals("TRUE") || value.toUpperCase().equals("false")) {
							return (T) (Object) Boolean.parseBoolean(value);
						} else {
							throw new SysException("--不能转换!--");
						}
					case "boolean":
						if (value.toUpperCase().equals("TRUE") || value.toUpperCase().equals("false")) {
							return (T) (Object) Boolean.parseBoolean(value);
						} else {
							throw new SysException("--不能转换!--");
						}
					}
					break;
				case "java.lang.Integer":
					Integer integerValue = (Integer) source;
					switch (targetClazzName) {
					case "java.lang.Integer":
						return (T) (Object) integerValue;
					case "int":
						return (T) (Object) integerValue;
					case "java.lang.Long":
						return (T) (Object) (long) integerValue.intValue();
					case "long":
						return (T) (Object) (long) integerValue.intValue();
					case "java.lang.Float":
						return (T) (Object) (float) integerValue.intValue();
					case "float":
						return (T) (Object) (float) integerValue.intValue();
					case "java.lang.Double":
						return (T) (Object) (double) integerValue.intValue();
					case "double":
						return (T) (Object) (double) integerValue.intValue();
					case "java.lang.Boolean":
						throw new SysException("--不能转换!--");
					case "boolean":
						throw new SysException("--不能转换!--");
					case "java.lang.String":
						return (T) (Object) String.valueOf(integerValue.intValue());
					}
					break;
				case "int":
					Integer intValue = (Integer) source;
					switch (targetClazzName) {
					case "java.lang.Integer":
						return (T) (Object) intValue;
					case "int":
						return (T) (Object) intValue;
					case "java.lang.Long":
						return (T) (Object) (long) intValue;
					case "long":
						return (T) (Object) (long) intValue;
					case "java.lang.Float":
						return (T) (Object) (float) intValue;
					case "float":
						return (T) (Object) (float) intValue;
					case "java.lang.Double":
						return (T) (Object) (double) intValue;
					case "double":
						return (T) (Object) (double) intValue;
					case "java.lang.Boolean":
						throw new SysException("--不能转换!--");
					case "boolean":
						throw new SysException("--不能转换!--");
					case "java.lang.String":
						return (T) (Object) String.valueOf(intValue);
					}
					break;
				case "java.lang.Long":
					Long _longValue = (Long) source;
					switch (targetClazzName) {
					case "java.lang.Integer":
						return (T) (Object) (int) _longValue.intValue();
					case "int":
						return (T) (Object) (int) _longValue.intValue();
					case "java.lang.Long":
						return (T) (Object) (long) _longValue;
					case "long":
						return (T) (Object) (long) _longValue;
					case "java.lang.Float":
						return (T) (Object) (float) _longValue.floatValue();
					case "float":
						return (T) (Object) (float) _longValue.floatValue();
					case "java.lang.Double":
						return (T) (Object) (double) _longValue.doubleValue();
					case "double":
						return (T) (Object) (double) _longValue.doubleValue();
					case "java.lang.Boolean":
						throw new SysException("--不能转换!--");
					case "boolean":
						throw new SysException("--不能转换!--");
					case "java.lang.String":
						return (T) (Object) String.valueOf(_longValue.longValue());
					}
					break;
				case "long":
					Long longValue = (Long) source;
					switch (targetClazzName) {
					case "java.lang.Integer":
						return (T) (Object) (int) longValue.intValue();
					case "int":
						return (T) (Object) (int) longValue.intValue();
					case "java.lang.Long":
						return (T) (Object) (long) longValue;
					case "long":
						return (T) (Object) (long) longValue;
					case "java.lang.Float":
						return (T) (Object) (float) longValue.floatValue();
					case "float":
						return (T) (Object) (float) longValue.floatValue();
					case "java.lang.Double":
						return (T) (Object) (double) longValue.doubleValue();
					case "double":
						return (T) (Object) (double) longValue.doubleValue();
					case "java.lang.Boolean":
						throw new SysException("--不能转换!--");
					case "boolean":
						throw new SysException("--不能转换!--");
					case "java.lang.String":
						return (T) (Object) String.valueOf(longValue.longValue());
					}
					break;
				case "java.lang.Float":
					Float floatValue = (Float) source;
					switch (targetClazzName) {
					case "java.lang.Integer":
						return (T) (Object) (int) floatValue.intValue();
					case "int":
						return (T) (Object) (int) floatValue.intValue();
					case "java.lang.Long":
						return (T) (Object) (long) floatValue.longValue();
					case "long":
						return (T) (Object) (long) floatValue.longValue();
					case "java.lang.Float":
						return (T) (Object) (float) floatValue;
					case "float":
						return (T) (Object) (float) floatValue;
					case "java.lang.Double":
						return (T) (Object) (double) floatValue.doubleValue();
					case "double":
						return (T) (Object) (double) floatValue.doubleValue();
					case "java.lang.Boolean":
						throw new SysException("--不能转换!--");
					case "boolean":
						throw new SysException("--不能转换!--");
					case "java.lang.String":
						return (T) (Object) String.valueOf(floatValue.floatValue());
					}
					break;
				case "float":
					Float _floatValue = (Float) source;
					switch (targetClazzName) {
					case "java.lang.Integer":
						return (T) (Object) (int) _floatValue.intValue();
					case "int":
						return (T) (Object) (int) _floatValue.intValue();
					case "java.lang.Long":
						return (T) (Object) (long) _floatValue.longValue();
					case "long":
						return (T) (Object) (long) _floatValue.longValue();
					case "java.lang.Float":
						return (T) (Object) (float) _floatValue;
					case "float":
						return (T) (Object) (float) _floatValue;
					case "java.lang.Double":
						return (T) (Object) (double) _floatValue.doubleValue();
					case "double":
						return (T) (Object) (double) _floatValue.doubleValue();
					case "java.lang.Boolean":
						throw new SysException("--不能转换!--");
					case "boolean":
						throw new SysException("--不能转换!--");
					case "java.lang.String":
						return (T) (Object) String.valueOf(_floatValue.floatValue());
					}
					break;
				case "java.lang.Double":
					Double doubleVal = (Double) source;
					switch (targetClazzName) {
					case "java.lang.Integer":
						return (T) (Object) (int) doubleVal.intValue();
					case "int":
						return (T) (Object) (int) doubleVal.intValue();
					case "java.lang.Long":
						return (T) (Object) (long) doubleVal.longValue();
					case "long":
						return (T) (Object) (long) doubleVal.longValue();
					case "java.lang.Float":
						return (T) (Object) (float) doubleVal.floatValue();
					case "float":
						return (T) (Object) (float) doubleVal.floatValue();
					case "java.lang.Double":
						return (T) (Object) (double) doubleVal;
					case "double":
						return (T) (Object) (double) doubleVal;
					case "java.lang.Boolean":
						throw new SysException("--不能转换!--");
					case "boolean":
						throw new SysException("--不能转换!--");
					case "java.lang.String":
						return (T) (Object) String.valueOf(doubleVal.doubleValue());
					}
					break;
				case "double":
					Double _doubleVal = (Double) source;
					switch (targetClazzName) {
					case "java.lang.Integer":
						return (T) (Object) (int) _doubleVal.intValue();
					case "int":
						return (T) (Object) (int) _doubleVal.intValue();
					case "java.lang.Long":
						return (T) (Object) (long) _doubleVal.longValue();
					case "long":
						return (T) (Object) (long) _doubleVal.longValue();
					case "java.lang.Float":
						return (T) (Object) (float) _doubleVal.floatValue();
					case "float":
						return (T) (Object) (float) _doubleVal.floatValue();
					case "java.lang.Double":
						return (T) (Object) (double) _doubleVal;
					case "double":
						return (T) (Object) (double) _doubleVal;
					case "java.lang.Boolean":
						throw new SysException("--不能转换!--");
					case "boolean":
						throw new SysException("--不能转换!--");
					case "java.lang.String":
						return (T) (Object) String.valueOf(_doubleVal.doubleValue());
					}
					break;
				}
			}
		}
		throw new SysException("不能转换！");
	}

	public byte[] readFile(String fileName) throws SysException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(fileName);
			int count = 0;
			byte[] buf = new byte[1024];
			while ((count = fis.read(buf)) != -1) {
				baos.write(buf, 0, count);
			}
		} catch (Exception e) {
			throw new SysException(e);
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {

				}
			}
		}
		return baos.toByteArray();
	}

	public void copySimplePropsFormMapToBean(Object bean, Map<String, Object> map, String... props)
			throws SysException {
		Class<?> clazz = bean.getClass();
		Method[] allMethods = clazz.getMethods();
		if (allMethods == null || allMethods.length == 0)
			throw new SysException();
		List<Method> setters = new ArrayList<Method>();
		for (Method m : allMethods) {
			if (m.getName().startsWith("set") && m.getParameterTypes() != null && m.getParameterTypes().length == 1) {
				setters.add(m);
			}
		}
		PROPSET: for (String propName : props) {
			String setterName = "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
			@SuppressWarnings("unused")
			String getterName = "get" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
			Method method = null;
			for (Method m : setters) {
				if (m.getName().equals(setterName))
					method = m;
			}
			Object mapValue = map.get(propName);
			if (method != null) {
				if (mapValue == null) {
					try {
						method.invoke(bean, mapValue);
						continue PROPSET;
					} catch (Exception e) {
						throw new SysException(e);
					}
				}
				Class<?> parType = method.getParameterTypes()[0];
				Class<?> valClass = mapValue.getClass();
				if (parType == String.class) {
					if (valClass == String.class) {
						try {
							method.invoke(bean, (String) mapValue);
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else if (valClass == Long.class || valClass == long.class) {
						try {
							method.invoke(bean, String.valueOf((Long) mapValue));
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else if (valClass == Integer.class || valClass == int.class) {
						try {
							method.invoke(bean, String.valueOf((Integer) mapValue));
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else if (valClass == Date.class) {
						try {
							method.invoke(bean, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) mapValue));
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else {
						try {
							method.invoke(bean, mapValue.toString());
						} catch (Exception e) {
							throw new SysException(e);
						}
					}
				} else if (parType == Long.class || parType == long.class) {
					if (valClass == Long.class || valClass == long.class) {
						try {
							method.invoke(bean, (Long) mapValue);
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else if (valClass == Integer.class || valClass == int.class) {
						try {
							method.invoke(bean, Long.valueOf(String.valueOf((Integer) mapValue)));
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else if (valClass == String.class) {
						try {
							method.invoke(bean, Long.valueOf((String) mapValue));
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else if (valClass == Date.class) {
						try {
							method.invoke(bean, ((Date) mapValue).getTime());
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else {
						try {
							method.invoke(bean, mapValue);
						} catch (Exception e) {
							throw new SysException(e);
						}
					}
				} else if (parType == Integer.class || parType == int.class) {
					if (valClass == String.class) {
						try {
							method.invoke(bean, Integer.valueOf((String) mapValue));
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else if (valClass == Long.class || valClass == long.class) {
						try {
							method.invoke(bean, Integer.valueOf(String.valueOf((Long) mapValue)));
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else if (valClass == Integer.class || valClass == int.class) {
						try {
							method.invoke(bean, (Integer) mapValue);
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else {
						try {
							method.invoke(bean, mapValue);
						} catch (Exception e) {
							throw new SysException(e);
						}
					}
				} else if (parType == Date.class) {
					if (valClass == String.class) {
						String val = (String) mapValue;
						Date dVal = null;
						try {
							dVal = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(val);
						} catch (ParseException e) {
							try {
								dVal = new SimpleDateFormat("yyyy-MM-dd").parse(val);
							} catch (ParseException e1) {
								throw new SysException(e1);
							}
						}
						if (dVal != null) {
							try {
								method.invoke(bean, dVal);
							} catch (Exception e) {
								throw new SysException(e);
							}
						} else {
							throw new SysException("");
						}
					} else if (valClass == Date.class) {
						try {
							method.invoke(bean, (Date) mapValue);
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else if (valClass == Long.class || valClass == long.class) {
						Calendar c = Calendar.getInstance();
						c.setTimeInMillis((Long) mapValue);
						Date dVal = c.getTime();
						try {
							method.invoke(bean, dVal);
						} catch (Exception e) {
							throw new SysException(e);
						}
					} else {
						try {
							method.invoke(bean, mapValue);
						} catch (Exception e) {
							throw new SysException(e);
						}
					}
				} else if (parType == Boolean.class || parType == boolean.class) {
					String[] TRUES = new String[] { "Y", "YES", "T", "TRUE", "SUCCESS", "1" };
					String[] FALSES = new String[] { "N", "NO", "F", "FALSE", "FALURE", "0" };

					if (valClass == String.class) {
						String sVal = (String) mapValue;
						Boolean bVal = null;
						for (String s : TRUES) {
							if (sVal.trim().equals(s))
								bVal = true;
						}
						for (String s : FALSES) {
							if (sVal.trim().equals(s))
								bVal = false;
						}
						try {
							method.invoke(bean, bVal);
						} catch (Exception e) {
							e.printStackTrace();
						}
					} else if (valClass == Boolean.class || valClass == boolean.class) {
						try {
							method.invoke(bean, (Boolean) mapValue);
						} catch (Exception e) {
							e.printStackTrace();
						}
					} else {
						try {
							method.invoke(bean, mapValue);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				} else if (parType == Double.class || parType == double.class) {
					if (valClass == String.class) {
						try {
							method.invoke(bean, Double.valueOf((String) mapValue));
						} catch (Exception e) {
							e.printStackTrace();
						}
					} else if (valClass == Double.class || valClass == double.class) {
						try {
							method.invoke(bean, mapValue);
						} catch (Exception e) {
							e.printStackTrace();
						}
					} else if (valClass == Integer.class || valClass == int.class) {
						try {
							method.invoke(bean, Double.valueOf(String.valueOf((Integer) mapValue)));
						} catch (Exception e) {
							e.printStackTrace();
						}
					} else if (valClass == Long.class || valClass == long.class) {
						try {
							method.invoke(bean, Double.valueOf(String.valueOf((Long) mapValue)));
						} catch (Exception e) {
							e.printStackTrace();
						}
					} else if (valClass == Float.class || valClass == float.class) {
						try {
							method.invoke(bean, Double.valueOf(String.valueOf((Float) mapValue)));
						} catch (Exception e) {
							e.printStackTrace();
						}
					} else {
						try {
							method.invoke(bean, mapValue);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				} else {
					throw new SysException("未知错误！");
				}
			} else {
				throw new SysException("错误！");
			}
		}
	}

	public boolean isNullOrEmptyString(String a) {
		if (a == null || a.equals(""))
			return true;
		return false;
	}

	public boolean isNumber(String s) {
		if (s == null)
			return false;
		if (s.matches("\\d+"))
			return true;
		return false;
	}

	public String uuid() {
		return UUID.randomUUID().toString().replace("-", "");
	}

	public static final void main(String[] args) throws SysException {
		String uuid = CommonMethod.getInstance().uuid();
		Class<String> stringClass = (Class<String>) uuid.getClass();
		System.out.println(stringClass.getName());
		System.out.println(stringClass.getSimpleName());
		System.out.println(Object.class.isAssignableFrom(String.class));
		System.out.println(int.class.getName());
		System.out.println(Boolean.parseBoolean("Yes"));
		System.out.println(((Long) (555L)).intValue());
		System.out.println(getInstance().baseCast("2.2", Double.class).getClass());
	}

	public Method findSetterByPropName(Class<?> clazz, String propName) throws SysException {
		String setterName = "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
		Method[] all = clazz.getMethods();
		List<Method> setters = new ArrayList<Method>();
		if (all != null) {
			for (Method m : all) {
				String methodName = m.getName();
				if (methodName.equals(setterName) && m.getParameterTypes() != null && m.getParameterTypes().length == 1)
					setters.add(m);
			}
		}
		if (setters == null || setters.size() == 0) {
			throw new SysException(new NoSuchMethodException("Not Found Setter!"));
		} else if (setters.size() > 1) {
			throw new SysException("Threr is more than one stter found!");
		}
		return setters.get(0);
	}

	public boolean isEqual(byte[] a, byte[] b) {
		boolean isEquals = true;
		if (a.length == b.length) {
			for (int i = 0; i < a.length; i++) {
				if (a[i] != b[i]) {
					isEquals = false;
				}
			}
		} else {
			isEquals = false;
		}
		return isEquals;
	}

}
